//
//  MultiShotLocationManager.swift
//  ezyform
//
//  Created by MoennigQ on 12/8/19.
//  Copyright © 2019 Client.Solution Pty Ltd. All rights reserved.
//  持续定位

import Foundation
import CoreLocation
//possible errors
enum LocationManagerErrors: Int {
    case authorizationDenied
    case authorizationNotDetermined
    case invalidLocation
}
enum GPSSubscription: Int {
    case single
    case continous
}
class LocationManager: NSObject, CLLocationManagerDelegate {
    
    class var shared: LocationManager {
        struct Inner {
            static let instance: LocationManager = LocationManager()
        }
        return Inner.instance
    }
    //location manager
    fileprivate var manager: CLLocationManager?
    //location manager
    internal var gpsSubscription: GPSSubscription = .single
    internal func subscription(_ subscription: GPSSubscription)->Self{
        self.gpsSubscription = subscription
        return self
    }
    //destroy the manager
    deinit {
        self.releaseManager()
    }
    
    func releaseManager()  {
        manager?.stopUpdatingLocation()
        manager?.delegate = nil
        manager = nil
        DebugLog("GPS定位LocationManager deinit")
    }
    
    typealias LocationClosure = ((_ location: CLLocation?, _ error: NSError?)->())
    fileprivate var didComplete: LocationClosure?
    
    //location manager returned, call didcomplete closure
    fileprivate func _didComplete(_ location: CLLocation?, error: NSError?) {
        didComplete?(location, error)
    }
    
    //location authorization status changed
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        
        switch status {
        case .authorizedWhenInUse,.authorizedAlways:
            self.manager?.startUpdatingLocation()
        case .denied:
            _didComplete(nil, error: NSError(domain: self.classForCoder.description(),
                                             code: LocationManagerErrors.authorizationDenied.rawValue,
                                             userInfo: nil))
        default:
            break
        }
    }
    
    internal func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        _didComplete(nil, error: error as NSError?)
    }
    
    internal func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        //单次定位，获取定位后自动释放Location manager
        if gpsSubscription == .single {
            self.releaseManager()
        }
        if let location : CLLocation = locations.last {
            _didComplete(location, error: nil)
        } else {
            _didComplete(nil, error: NSError(domain: self.classForCoder.description(),
                                             code: LocationManagerErrors.invalidLocation.rawValue,
                                             userInfo: nil))
        }
    }
    //ask for location permissions, fetch 1 location, and return
    func fetchWithCompletion(_ completion: @escaping LocationClosure) {
        //store the completion closure
        didComplete = completion
        
        //fire the location manager
        manager = CLLocationManager()
        manager?.delegate = self
        manager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation//最佳，導航用高精準度（精确度越高，越耗电，定位所需时间越长）
        manager?.distanceFilter = 1 //移动一米定位一次
        manager?.activityType = .fitness//健身：ex.步行、跑步、游泳等
        
        //check for description key and ask permissions
        if (Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil) {
            manager?.requestWhenInUseAuthorization()
        } else if (Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil) {
            manager?.requestAlwaysAuthorization()
        } else {
            fatalError("To use location in iOS8 you need to define either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription in the app bundle's Info.plist file")
        }
        
    }
}
